package com.gxp.controller.game;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.support.RequestContextUtils;

import com.gxp.pojo.Game;
import com.gxp.pojo.GameGoods;
import com.gxp.pojo.GameServer;
import com.gxp.pojo.GameType;
import com.gxp.pojo.Order;
import com.gxp.pojo.WXOrder;
import com.gxp.service.GameService;
import com.gxp.service.OrderService;
import com.gxp.util.common.GXPConstant;
import com.gxp.util.common.GXPUtil;
import com.gxp.util.databind.DateEditor;


@Controller
public class GameController {
	
	Logger logger = Logger.getLogger(GameController.class);

	@Autowired
	private GameService gameService;
	
	@Autowired
	private OrderService orderService;
	
	@InitBinder
	protected void initBinder(HttpServletRequest request,
	                              ServletRequestDataBinder binder) throws Exception {
	    binder.registerCustomEditor(Date.class, new DateEditor());
	}

	@RequestMapping(value="/admin/game/add",method=RequestMethod.GET)
	@PreAuthorize("hasAnyRole('ROLE_ADMIN_ALL','ROLE_ADMIN_GOODS') and hasRole('PERM_GAME_ADD')")
	public ModelAndView addGame() {
		
		logger.debug("Game controller is addGame invoked.........");
		List<GameType> types = gameService.getGameTypes();
		logger.debug("type size: " +  types.size());
		ModelAndView mav = new ModelAndView();
		mav.addObject("gameTypes", types);
		mav.setViewName("admin/product/game/gameAdd");
		return mav;
	}
	
	@RequestMapping(value="/admin/game/edit/{gameId}",method=RequestMethod.GET)
	@PreAuthorize("hasAnyRole('ROLE_ADMIN_ALL','ROLE_ADMIN_GOODS') and hasRole('PERM_GAME_UPDATE')")
	public ModelAndView editGame(@PathVariable int gameId, Model model) {
		
		ModelAndView mav = new ModelAndView();
		
		logger.debug("Game controller is editGame invoked.........");
		List<GameType> types = gameService.getGameTypes();
		Game game = gameService.getGame(gameId);
		logger.debug("type size: " +  types.size());
		mav.addObject("gameTypes", types);
		mav.addObject("game",game);
		mav.addObject("actionGameId", gameId);
		mav.setViewName("admin/product/game/gameEdit");
		return mav;		
	}
	
	@RequestMapping(value="/admin/game/save",method=RequestMethod.POST)
	@PreAuthorize("hasAnyRole('ROLE_ADMIN_ALL','ROLE_ADMIN_GOODS') and hasRole('PERM_GAME_ADD')")
	@ResponseBody
	public String saveGame(Game gameInput) {
		
		logger.debug("Save Game controller is saveGame invoked.........");
		logger.debug("game name: " + gameInput.getName());
		logger.debug("game getCompany: " + gameInput.getCompany());
		logger.debug("game getCost: " + gameInput.getCost());
		logger.debug("game getDownloadMethod: " + gameInput.getDownloadMethod());
		logger.debug("game getKeywords: " + gameInput.getKeywords());
		logger.debug("game getLogoUrl: " + gameInput.getLogoUrl());
		logger.debug("game getProduceMethod: " + gameInput.getProduceMethod());
		logger.debug("game getUrl: " + gameInput.getUrl());
		logger.debug("game getFeasibility: " + gameInput.getFeasibility());
		logger.debug("game getPopularity: " + gameInput.getPopularity());
		logger.debug("game getTypeId: " + gameInput.getTypeId());
		logger.debug("game getStartDt: " + gameInput.getStartDt());
		
		if (!StringUtils.hasText(gameInput.getName())) {
			return "failed";
		}
		
		gameService.saveGame(gameInput);
		
		return "success";
	}
	
	@RequestMapping(value="/admin/game/update",method=RequestMethod.POST)
	@PreAuthorize("hasAnyRole('ROLE_ADMIN_ALL','ROLE_ADMIN_GOODS') and hasRole('PERM_GAME_UPDATE')")
	@ResponseBody
	public String updateGame(Game gameInput) {
		logger.debug("Save Game controller is updateGame invoked.........");
		logger.debug("game name: " + gameInput.getName());
		logger.debug("game getCompany: " + gameInput.getCompany());
		logger.debug("game getCost: " + gameInput.getCost());
		logger.debug("game getDownloadMethod: " + gameInput.getDownloadMethod());
		logger.debug("game getKeywords: " + gameInput.getKeywords());
		logger.debug("game getLogoUrl: " + gameInput.getLogoUrl());
		logger.debug("game getProduceMethod: " + gameInput.getProduceMethod());
		logger.debug("game getUrl: " + gameInput.getUrl());
		logger.debug("game getFeasibility: " + gameInput.getFeasibility());
		logger.debug("game getPopularity: " + gameInput.getPopularity());
		logger.debug("game getTypeId: " + gameInput.getTypeId());
		logger.debug("game getStartDt: " + gameInput.getStartDt());
		
		if (!StringUtils.hasText(gameInput.getName())) {
			return "failed";
		}
		gameService.updateGame(gameInput);
		
		return "success";
	}
	
	@RequestMapping(value="/admin/game/server/maintain",method=RequestMethod.GET)
	public ModelAndView addGameServer() {
		logger.debug("Game controller addGameServer is invoked.........");
		List<Game> games = gameService.getGames();
		logger.debug("games size: " +  games.size());
		ModelAndView mav = new ModelAndView();
		mav.addObject("games", games);
		mav.setViewName("admin/product/game/gameServer");
		return mav;		
	}
	
	@RequestMapping(value="/admin/game/server/get",method=RequestMethod.POST)
	@ResponseBody
	public List<GameServer> getGameServer(Integer gameId) {
		logger.debug("Game controller getGameServer is invoked.........");
		List<GameServer> gameServers = gameService.getGameServers(gameId);
		logger.debug("gameServers size: " +  gameServers.size());		
		return gameServers;		
	}
	
	@RequestMapping(value="/admin/game/server/save",method=RequestMethod.POST)
	@ResponseBody
	public List<GameServer> saveGameServer(GameServer serverInput, Model model) {
		logger.debug("Save Game controller is saveGameServer invoked.........");
		logger.debug("server name: " + serverInput.getName());
		logger.debug("server keywords: " + serverInput.getKeywords());
		gameService.saveGameServer(serverInput);
		List<GameServer> servers = gameService.getGameServers(serverInput.getGameId());
		logger.debug("servers: " + servers.size());
		return servers;
	}
	
	@RequestMapping(value="/admin/game/server/status/update/{gameId}/{serverId}/{status}",method=RequestMethod.POST)
	@ResponseBody
	public List<GameServer> activeGameServer(@PathVariable int gameId, @PathVariable int serverId, @PathVariable int status) {
		logger.debug("Active Game controller is activeGameServer invoked.........");
		logger.debug("gameId: " +gameId);
		logger.debug("serverId: " + serverId);
		Map<String,Object> param = new HashMap<String, Object>();
		param.put(GXPConstant.MAPPER_KEY_SERVER_ID, serverId);
		param.put(GXPConstant.MAPPER_KEY_NEW_STATUS, status);
		gameService.updateServerStatus(param);
		List<GameServer> servers = gameService.getGameServers(gameId);
		return servers;
	}	
	
	@RequestMapping(value="/admin/game/server/update/{gameId}/{serverId}",method=RequestMethod.POST)
	@ResponseBody
	public List<GameServer> updGameServer(@PathVariable int gameId, @PathVariable int serverId, GameServer gameServer) {
		gameServer.setGameId(gameId);
		gameServer.setServerId(serverId);
		logger.debug("Game controller is updGameServer invoked.........");
		logger.debug("gameId: " +gameId);
		logger.debug("serverId: " + serverId);
		gameService.updateServer(gameServer);
		List<GameServer> servers = gameService.getGameServers(gameId);
		return servers;
	}
	
	@RequestMapping(value="/admin/game/server/delete/{gameId}/{serverId}",method=RequestMethod.POST)
	@ResponseBody
	public List<GameServer> delGameServer(@PathVariable int gameId, @PathVariable int serverId,
			HttpServletRequest request,HttpServletResponse response) {
		logger.debug("Game controller is delGameServer invoked.........");
		logger.debug("gameId: " +gameId);
		logger.debug("serverId: " + serverId);
		Map<String, Object> param1 = new HashMap<String, Object>();
		param1.put(GXPConstant.MAPPER_KEY_SERVER_ID, serverId);
		List<Order> orders = orderService.findBuyerOrders(param1);
		List<GameServer> servers = null;
		
		if (orders != null && !orders.isEmpty()) {
			response.setContentType("text/html;charset=UTF-8");
			ApplicationContext ctx = RequestContextUtils.getWebApplicationContext(request);
			String fileTypeError = ctx.getMessage("msg.delete.equipment.error", null, RequestContextUtils.getLocale(request));
			try {
				PrintWriter out = response.getWriter();				
				out.write("{\"ERROR\":\"" + fileTypeError + "\"}");
			    out.flush();
			    out.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		} else {
			Map<String,Object> param = new HashMap<String, Object>();
			param.put(GXPConstant.MAPPER_KEY_SERVER_ID, serverId);
			param.put(GXPConstant.MAPPER_KEY_NEW_STATUS, -1);
			gameService.updateServerStatus(param);
			servers = gameService.getGameServers(gameId);
		}	
		
		return servers;
	}
	
	
	@RequestMapping(value="/admin/game/list",method=RequestMethod.GET)
	@PreAuthorize("hasAnyRole('ROLE_ADMIN_ALL','ROLE_ADMIN_GOODS') and hasRole('PERM_GAME_VIEW')")
	public ModelAndView maintainGame() {
		logger.debug("Game controller maintainGame is invoked.........");
		List<Game> games = gameService.getGames();
		logger.debug("games size: " +  games.size());
		ModelAndView mav = new ModelAndView();
		mav.addObject("games", games);
		mav.setViewName("admin/product/game/gameList");
		return mav;		
	}
	
	@RequestMapping(value="/admin/game/status/update/{gameId}/{status}",method=RequestMethod.POST,produces=MediaType.APPLICATION_JSON_VALUE)
	@PreAuthorize("hasAnyRole('ROLE_ADMIN_ALL','ROLE_ADMIN_GOODS') and hasRole('PERM_GAME_UPDATE')")
	@ResponseBody
	public String updateGameStatus(@PathVariable int gameId, @PathVariable int status) {
		logger.debug("Game controller updateGameStatus is invoked.........");
		logger.debug("gameId: " +gameId);
		Map<String,Object> param = new HashMap<String, Object>();
		param.put(GXPConstant.MAPPER_KEY_GAME_ID, gameId);
		param.put(GXPConstant.MAPPER_KEY_NEW_STATUS, status);
		gameService.updateGameStatus(param);
		return GXPUtil.getJsonString("success", false, String.valueOf(status));
	}
	
	@RequestMapping(value="/admin/game/delete/{gameId}",method=RequestMethod.POST)
	@PreAuthorize("hasAnyRole('ROLE_ADMIN_ALL','ROLE_ADMIN_GOODS') and hasRole('PERM_GAME_UPDATE')")
	@ResponseBody
	public List<Game> deleteGame(@PathVariable int gameId,
			HttpServletRequest request,HttpServletResponse response) {
		logger.debug("Game controller is deleteGame invoked.........");
		logger.debug("gameId: " +gameId);
		
		Map<String, Object> param1 = new HashMap<String, Object>();
		param1.put(GXPConstant.MAPPER_KEY_GAME_ID, gameId);
		List<Order> orders = orderService.findBuyerOrders(param1);		
		List<GameServer> servers = gameService.getGameServers(gameId);
		List<Game> games = null;
		if (orders != null && !orders.isEmpty() || servers != null && !servers.isEmpty()) {
			response.setContentType("text/html;charset=UTF-8");
			ApplicationContext ctx = RequestContextUtils.getWebApplicationContext(request);
			String fileTypeError = ctx.getMessage("msg.delete.game.error", null, RequestContextUtils.getLocale(request));
			try {
				PrintWriter out = response.getWriter();				
				out.write("{\"ERROR\":\"" + fileTypeError + "\"}");
			    out.flush();
			    out.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		} else {
			Map<String,Object> param = new HashMap<String, Object>();
			param.put(GXPConstant.MAPPER_KEY_GAME_ID, gameId);
			param.put(GXPConstant.MAPPER_KEY_NEW_STATUS, -1);
			gameService.updateGameStatus(param);
			games = gameService.getGames();
		}
		
		
		return games;
	}
	
	@RequestMapping(value="/admin/game/view/{gameId}",method=RequestMethod.POST)
	@ResponseBody
	public Game viewGame(@PathVariable int gameId) {
		logger.debug("Game controller is viewGame invoked.........");
		logger.debug("gameId: " +gameId);
		return gameService.getGame(gameId);
	}
	
	@RequestMapping(value="/wx/gameIntro",method=RequestMethod.GET)
	public ModelAndView gameIntro() {
		logger.debug("Game controller gameIntro is invoked.........");
		List<Game> games = gameService.getGames();
		logger.debug("games size: " +  games.size());
		ModelAndView mav = new ModelAndView();
		mav.addObject("games", games);
		mav.setViewName("wx/template/gameIntro");
		return mav;		
	}
	
	@RequestMapping(value="/wx/gameServerIntro/{gameId}",method=RequestMethod.GET)
	public ModelAndView getGameServerIntro(@PathVariable int gameId) {
		logger.debug("Game controller getGameServerIntro is invoked.........");
		List<GameServer> gameServers = gameService.getGameServers(gameId);
		Game game = gameService.getGame(gameId);
		List<GameGoods> equips =  gameService.getEquipments(gameId);
		ModelAndView mav = new ModelAndView();
		mav.addObject("gameservers", gameServers);
		mav.addObject("game", game);
		mav.addObject("gameequips", equips);
		mav.setViewName("wx/template/gameServerIntro");
		return mav;	
	}
	
	@RequestMapping(value="/wx/orderInfo/{orderId}/{userId}",method=RequestMethod.GET)
	public ModelAndView getOrderInfo(@PathVariable int orderId, @PathVariable String userId) {
		logger.debug("Game controller getOrderInfo for wx is invoked.........");
		Map<String, Object> param = new HashMap<String, Object>();
		param.put(GXPConstant.MAPPER_KEY_ORDER_ID, orderId);
		param.put(GXPConstant.MAPPER_KEY_USER_ID, userId);
		WXOrder orderInfo = orderService.getWxOrder(param);
		logger.debug("orderInfo" + orderInfo.getOrderId());
		ModelAndView mav = new ModelAndView();
		mav.addObject("orderInfo", orderInfo);
		mav.setViewName("wx/template/orderInfo");
		return mav;	
	}
}
